package ru.hh.school.client;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Открывает консоль с чатом, в котором отображаются сообщения приходящие пользователю с ChatServer,
 * а также ожидает соединения с ClientInputConsole.
 * После получения соединения, пробрасывает ввод с ClientInputConsole на ChatServer.
 */
public final class ClientChatConsole {
    private ClientChatConsole() {
    }

    private static final int CHAT_SERVER_PORT = 12345;
    public static final String GREETINGS = "    //    / / //    / /       //   ) )  //    / / // | |  /__  ___/ \n" +
            "   //___ / / //___ / /       //        //___ / / //__| |    / /     \n" +
            "  / ___   / / ___   /       //        / ___   / / ___  |   / /      \n" +
            " //    / / //    / /       //        //    / / //    | |  / /       \n" +
            "//    / / //    / /       ((____/ / //    / / //     | | / /        \n" +
            "Hello! Please introduce yourself with login and password.\n" +
            "After that, you can use /help command to view list of available commands.";

    public static void main(String[] args) {

        final int port = Util.readPortFromAppArgs(args);
        String chatServerHostName = Util.readServerHostnameFromAppArgs(args);
        if (port == -1) {
            return;
        }
        if (chatServerHostName == null) {
            chatServerHostName = "localhost";
        }

        Socket clientEndpoint = null;
        ServerSocket localServerSocket = null;
        Socket localSocket = null;
        ClientInputHandler clientInputHandler = null;
        ObjectInputStream chatServerInputStream = null;
        try {
            clientEndpoint = new Socket(chatServerHostName, CHAT_SERVER_PORT);
            localServerSocket = new ServerSocket(port);
            // wait for ClientInputConsole connection
            localSocket = localServerSocket.accept();
            ObjectOutputStream clientEndpointOut = new ObjectOutputStream(clientEndpoint.getOutputStream());
            clientInputHandler = new ClientInputHandler(clientEndpointOut, localSocket.getInputStream(), Thread.currentThread());
            clientInputHandler.start();
            chatServerInputStream = new ObjectInputStream(clientEndpoint.getInputStream());
            Pattern privateMessagePattern = Pattern.compile("^\\$MAGIC\\$([0-9]*)\\$(.*)$");
            System.out.println(GREETINGS);
            while (!Thread.interrupted()) {
                String message = (String) chatServerInputStream.readObject();
                Matcher privateMessageMatcher = privateMessagePattern.matcher(message);
                if (privateMessageMatcher.matches()) {
                    String messageId = privateMessageMatcher.group(1);
                    message = privateMessageMatcher.group(2);
                    synchronized (clientEndpointOut) {
                        clientEndpointOut.writeObject("/confirm " + messageId);
                    }
                }
                System.out.println(message);
            }
        } catch (Exception e) {
            Util.ignoredException(e);
        } finally {
            if (clientInputHandler != null) {
                clientInputHandler.interrupt();
            }

            if (chatServerInputStream != null) {
                try {
                    chatServerInputStream.close();
                } catch (IOException e) {
                    Util.ignoredException(e);
                }
            }
            if (localSocket != null) {
                try {
                    localSocket.close();
                } catch (IOException e) {
                    Util.ignoredException(e);
                }
            }
            if (localServerSocket != null) {
                try {
                    localServerSocket.close();
                } catch (IOException e) {
                    Util.ignoredException(e);
                }
            }
            if (clientEndpoint != null) {
                try {
                    clientEndpoint.close();
                } catch (IOException e) {
                    Util.ignoredException(e);
                }
            }

        }
    }
}
